<?php
declare(strict_types=1);

namespace App\Service;

use App\Utils\CustomUtils;
use Hyperf\Di\Annotation\Inject;
use App\Model\Dao\MchSysAdminDao;
use App\Model\Dao\MchInfoDao;
use App\Model\Dao\MchSysRoleDao;
use App\Model\Dao\MchAdminForgotPasswordLogDao;
use App\Model\Dao\MchSysAdminMchRelationDao;
use App\Exception\XZXValidationException;
use App\Constants\XZXResponseCode;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Coroutine;
use App\Utils\DateUtils;
use App\Service\MchSysRoleService;
use Hyperf\Utils\Arr;
use App\Utils\OpenService;
use Phper666\JWTAuth\JWT;
use Hyperf\DbConnection\Db;
use App\Service\CommonService;
use App\Utils\StringUtils;
use App\Service\EmailService;
use App\Model\Enum\MchSysAdminStatusEnum;

class MchSysAdminService
{
    /**
     * @Inject()
     * @var JWT
     */
    private $JWT;

    /**
     * @Inject()
     * @var MchSysAdminMchRelationDao
     */
    private $MchSysAdminMchRelationDao;

    /**
     * @Inject()
     * @var MchAdminForgotPasswordLogDao
     */
    private $MchAdminForgotPasswordLogDao;    

    /**
     * @Inject()
     * @var MchSysAdminDao
     */
    private $MchSysAdminDao;

    /**
     * @Inject()
     * @var EmailService
     */
    private $EmailService;

    /**
     * @Inject()
     * @var MchSysRoleDao
     */
    private $MchSysRoleDao;

    /**
     * @Inject()
     * @var MchInfoDao
     */
    private $MchInfoDao;

    /**
     * @Inject()
     * @var MchSysRoleService
     */
    private $MchSysRoleService;

    /**
     * @Inject()
     * @var CommonService
     */
    private $CommonService;

    public function get($param)
    {
        $result = $this->MchSysAdminDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        if($param['source'] == 2 && !$param['isSuperRole']){
            if(!in_array($result['mchId'],$param['mchIdList'])){
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_PERMISSION_TO_OPERATE));
            }
        }  

        if($param['source'] == 1){            
            //从商户后台过来的请求
            if($result['mchId'] != $param['mchId']){
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_PERMISSION_TO_OPERATE));
            }  
        } 

        if(isset($result['createTime'])){
            $result['createTime'] = DateUtils::getDateTime($result['createTime']);
        }

        $roleResult = $this->MchSysRoleService->isSuperRole($result['roleId']);
        CustomUtils::xzxDebug($roleResult);
        if(!$roleResult['code'])
        {
            $result['isSuperRole'] = true;
        }        

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }

    public function del($param)
    {
        $result = $this->MchSysAdminDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        if($param['source'] == 1){            
            //从商户后台过来的请求
            if($result['mchId'] != $param['mchId']){
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_PERMISSION_TO_OPERATE));
            }  
        }        
        try {
            $result = $this->MchSysAdminDao->del($param['id'],false);
        } catch (\Throwable $th) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DEL_FAIL));
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function add($param)
    {
//        $salt        = OpenService::getNonceStr(5);
//        // $newPassword = md5($param['password'] . '*' . $salt);
//        $newPassword = CustomUtils::genPassWord($param['password'],$salt);
//
//        $data = $param;
//        $data['id'] = CustomUtils::createUUID();
//        $data['createTime'] = time();
//        $data['salt'] = $salt;
//        $data['password'] = $newPassword;
//        unset($data['password_confirmation']);
//        unset($data['from']);
//        CustomUtils::xzxDebug($data);

        Db::beginTransaction();
        try {
            $this->doAdd($param);
//            $this->MchSysAdminDao->insert($data);
//            try {
//                $this->HandleMchSysAdminMchRelation($data['id'],$param['mchId']);
//            } catch (\Throwable $th) {
//                CustomUtils::xzxDebug($th);
//                throw new XZXValidationException("添加管理员商户关系表失败");
//            }
        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th);
            Db::rollBack();
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::ADD_FAIL));
        }
        Db::commit();
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    /**
     * @param $param
     * 添加公共方法
     */
    public function doAdd($param) {
        $salt        = OpenService::getNonceStr(5);
        $newPassword = CustomUtils::genPassWord($param['password'],$salt);

        $data = $param;
        $data['id'] = CustomUtils::createUUID();
        $data['createTime'] = time();
        $data['salt'] = $salt;
        $data['password'] = $newPassword;
        // 生成GoogleAuth密钥
        $googleAuthSecret = $this->CommonService->generateGoogleAuthSecret();
        $data['googleAuthSecret'] = $googleAuthSecret;
        unset($data['password_confirmation']);
        unset($data['source']);
        CustomUtils::xzxDebug($data);
        $this->MchSysAdminDao->insert($data);
        $this->HandleMchSysAdminMchRelation($data['id'], $param['mchId']);
        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data); 
    }

    public function edit($param)
    {
        if($param['source'] == 2){
            $queryParam = array(
                'mchId' => $param['mchId'],
                'username' => 'admin',
            );
            $info1 = $this->MchSysAdminDao->getWhere($queryParam);
            if(!$info1)
            {
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));    
            }
            $param['id'] = $info1['id'];
        }
        $info = $this->MchSysAdminDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        if($param['source'] == 1){            
            //从商户后台过来的请求
            if($info['mchId'] != $param['mchId']){
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_PERMISSION_TO_OPERATE));
            }            
            //自己不能变更自己的状态
            if($param['uid'] == $param['id'] && $param['status'] != 1)
            {
                // throw new XZXValidationException("不能禁用自身状态");
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DO_NOT_DISABLE_SELF_STATUS));
            }

            $result = $this->MchSysRoleService->isSuperRole($info['roleId']);
            CustomUtils::xzxDebug($result);
            if(!$result['code'] && $param['status'] != 1)
            {
                // throw new XZXValidationException("不能禁用超级管理员账号");
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DO_NOT_DISABLE_ROOT));
            }
        }

        if($param['source'] == 2 && !$param['isSuperRole']){
            if(!in_array($info['mchId'],$param['mchIdList'])){
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_PERMISSION_TO_OPERATE));
            }
        }        

        $id = $param['id'];
        $data = array();
        
        foreach($param as $k => $v){
            if($k == "id"){
                continue;
            }            
            if(isset($v)){
                $data[$k] = $v;
            }
        }
        if(isset($param['source']) && $param['source'] == 2){
            //平台上的商户管理员的修改 目前仅支持修改密码
            CustomUtils::xzxDebug("平台管理员修改商户超级管理员密码");
            $salt = OpenService::getNonceStr(5);
            $newPassword      = md5($param['password'] . '*' . $salt);
            $data['password'] = $newPassword;
            $data['salt']     = $salt;    
            unset($data['isSuperRole']);
            
        }
        
        if(isset($param['source']) && $param['source'] == 1){
            if(isset($param['password'])){
                $salt = OpenService::getNonceStr(5);
                $newPassword      = md5($param['password'] . '*' . $salt);
                $data['password'] = $newPassword;
                $data['salt']     = $salt;   
            }
            unset($data['uid']);
        }
        unset($data['password_confirmation']);
        unset($data['source']);
        // unset($data['resetPassword']);
        
        // CustomUtils::xzxDebug($data);

        Db::beginTransaction();
        try {
            $this->MchSysAdminDao->update($id, $data);

            $this->MchSysAdminMchRelationDao->delWhere(['adminId' => $param['id']]);
            try {
                $this->HandleMchSysAdminMchRelation($param['id'],$param['mchId']);
            } catch (\Throwable $th) {
                // CustomUtils::xzxDebug($th);
                CustomUtils::xzxDebug("添加管理员商户关系表失败");
                // throw new XZXValidationException("添加管理员商户关系表失败");
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
            }
        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th);
            Db::rollBack();
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }
        Db::commit();
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function list(array $param)
    {

        $limit = $param['limit'];
        $page = $param['page'];        

        $total = $this->MchSysAdminDao->getCount($param);
        $list = $this->MchSysAdminDao->getList($param, $page, $limit);

        CustomUtils::xzxDebug($list);

        $roleOptions = $this->MchSysRoleService->getOptions($param)['data'];
        $roleOptions = array_column($roleOptions, 'label', 'value');

        foreach ($list as $k => $v) {
            CustomUtils::xzxDebug($v);
            unset($v['password']);
            unset($v['salt']);

            $v['strRole']    = Arr::get($roleOptions, $v['roleId'], '-');
            $v['strStatus']  = MchSysAdminStatusEnum::getLabel($v['status']);

            if(isset($v['createTime'])){
                $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            }
            $list[$k] = $v;
        }

        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }   
    
    
    public function login($param)
    {
        //读取商户信息
        $mchParam = array(
            'email'       => $param['email'],
            'loginStatus' => 1,
            // 'status'      => 1
        );
        $mch = $this->MchInfoDao->getWhere($mchParam);
        if(!$mch){
            // throw new XZXValidationException("无此商户");
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_MERCHANT));
        }
        if($mch['regStatus'] == 3)
        {
            // throw new XZXValidationException("无效商户");
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_REG_STATUS_FORBIDDEN));
        }

        if($mch['regStatus'] == 1 && $mch['status'] == 0){
            // throw new XZXValidationException("无此商户");
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_MERCHANT));
        }        

        // 读取用户信息
        $mchSysAdminParam = array(
            'username' => $param['username'],
            'mchId'    => $mch['id'],
            'status'   => 1
        );
        $user = $this->MchSysAdminDao->getWhere($mchSysAdminParam);
        if(!$user){
            // throw new XZXValidationException("无此用户");
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_USER));
        }

        //密码验证
        $verifiedPassword = CustomUtils::genPassWord($param['password'], $user["salt"]);
        //密码不等
        if ($verifiedPassword !== $user["password"]) {
            // throw new XZXValidationException('密码不一致');
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::PWD_DO_NOT_MATCH));
        }

        if(!config("isDev")){
            // 验证码验证
            $verifyRet = $this->CommonService->checkGoogleCode($user['googleAuthSecret'], $param['code']);
            if ($verifyRet['code']) {
                throw new XZXValidationException($verifyRet['message']);
            }
        }

        // 读取角色信息
        $role = $this->MchSysRoleDao->getWhere(['id' => $user['roleId'],'status' => 1]);
        if(!$role){
            // throw new XZXValidationException("角色不存在");
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_ROLE));
        }
        $isSuperRole = $role['type'] == 1;
        $user['isSuperRole'] = $isSuperRole;

        unset($user["salt"]);
        unset($user["password"]);
        unset($user['googleAuthSecret']);

        $this->JWT->setScene("mchapi");
        $user['mchNo'] = $param['mchNo'];
        $userData = array(   
            "uid"  => $user['id'],        
            "user" => $user,
            // "mch"  => $mch,
            // "role" => $role
        );
        $token = $this->JWT->getToken($userData);

        $returnData = $user;
        $returnData['mch'] = $mch;
        $returnData['role'] = $role;
        $data['token'] = $token;
        $data['user'] = $returnData;

        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    public function logout(array $param)
    {
        $member = $this->MchSysAdminDao->get($param['uid']);
        if (!$member) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        if(!$this->JWT->logout())
        {
            // throw new XZXValidationException('logout 失败');
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::LOGOUT_FAIL));
        }

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    } 


    private function HandleMchSysAdminMchRelation($adminId,$mchId){
        $admin_mch_relation_data = array(
            "id"         => CustomUtils::createUUID(),
            "adminId"    => $adminId,
            "mchId"      => $mchId,
            "createTime" => time(),
        );
        // CustomUtils::xzxDebug($admin_mch_relation_data);
        try {
            $this->MchSysAdminMchRelationDao->insert($admin_mch_relation_data);
        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th);
            throw new XZXValidationException("添加管理员商户关系表失败");
        }        
        return;
    }

    public function resetGoogleAuthSecret($param) {
        if($param['source'] == 2){
            $queryParam = array(
                'mchId' => $param['mchId'],
                'username' => 'admin',
            );
            $info1 = $this->MchSysAdminDao->getWhere($queryParam);
            if(!$info1)
            {
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));    
            }
            $param['id'] = $info1['id'];
        }        

        $info = $this->MchSysAdminDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        // 生成GoogleAuth密钥
        $googleAuthSecret = $this->CommonService->generateGoogleAuthSecret();
        // 更新用户
        $data = [
            'googleAuthSecret' => $googleAuthSecret
        ];
        try {
            $this->MchSysAdminDao->set($param['id'], $data);
        } catch (\Throwable $th) {
            //throw $th;
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }

        $sendMailParam = array(
            'type'  => 20,
            'email' => $info['email'],
            "googleAuthSecret" => $data['googleAuthSecret'],
        );
        CustomUtils::xzxDebug($sendMailParam);
        $this->EmailService->addMq($sendMailParam);
        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$googleAuthSecret);

    }

    public function forgotPassword($param){
        $queryParam = array(
            'email' => $param['mchEmail']
        );
        $info = $this->MchInfoDao->getWhere($queryParam);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }   
        unset($queryParam);
        $queryParam = array(
            'email' => $param['email']
        ); 
        $adminInfo = $this->MchSysAdminDao->getWhere($queryParam);
        if (!$adminInfo) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        
        $data = array();
        $data['id'] = CustomUtils::createUUID();
        $data['mchId'] = $info['id'];
        $data['mchNo'] = $info['mchNo'];
        $data['mchAdminEmail'] = $param['email'];
        $data['hashCode'] = date('YmdHis') . StringUtils::randNumber(8);
        $this->MchAdminForgotPasswordLogDao->insert($data);
        //todo send email
        $sendMailParam = array(
            'type'             => 14,
            'email'            => $param['email'],
            'hashCode'         => $data['hashCode'],
        );
        CustomUtils::xzxDebug($sendMailParam);
        $this->EmailService->addMq($sendMailParam);
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function resetPassword($param){
        $queryParam = array(
            'hashCode' => $param['hashCode']
        );
        $logInfo = $this->MchAdminForgotPasswordLogDao->getWhere($queryParam);
        if (!$logInfo) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }   
        if((time() - $logInfo['createTime']) > 3600){
            //超过1小时的不允许再访问，得再次发送忘记密码邮件
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }             

        unset($queryParam);
        $queryParam = array(
            'email' => $logInfo['mchAdminEmail']
        ); 
        $adminInfo = $this->MchSysAdminDao->getWhere($queryParam);
        if (!$adminInfo) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        if(!config("isDev")){
            // 验证码验证
            $verifyRet = $this->CommonService->checkGoogleCode($adminInfo['googleAuthSecret'], $param['code']);
            if ($verifyRet['code']) {
                throw new XZXValidationException($verifyRet['message']);
            }
        }        
        
        $salt = OpenService::getNonceStr(5);
        $newPassword      = md5($param['password'] . '*' . $salt);
        $data['password'] = $newPassword;
        $data['salt']     = $salt;  
        $this->MchSysAdminDao->update($adminInfo['id'], $data);
       
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    } 
    
    public function changePassword ($param) {

        // xeDebug($param);

        $user = $this->MchSysAdminDao->get($param['id']);

        if (!$user) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        // if(!$this->_verifyMchUserPassword($user, $param['passwordNow'])){
        //     CustomUtils::xzxDebug("密码不对");
        //     throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        // }

        //密码验证
        $verifiedPassword = CustomUtils::genPassWord($param['passwordNow'], $user["salt"]);
        //密码不等
        if ($verifiedPassword !== $user["password"]) {
            // throw new XZXValidationException('密码不一致');
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::PWD_DO_NOT_MATCH));
        }

        $salt = OpenService::getNonceStr(5);
        $passwordNew = md5($param['password'] . '*' . $salt);

        $salt = OpenService::getNonceStr(5);
        $newPassword      = md5($param['password'] . '*' . $salt);
        $data['password'] = $newPassword;
        $data['salt']     = $salt;  
        $data['needChangePwd'] = 0;
        $this->MchSysAdminDao->update($param['id'], $data);
        
        // 清除用户的登录Token
        // $this->MchMemberDao->delLoginInfo($user['id']);
        $this->JWT->logout();

        // $data = [];

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    // // 商户: 校验密码
    // protected function _verifyMchUserPassword ($user, $password) {

    //     $verifiedPassword = CustomUtils::genPassWord($password, $user["salt"]);
    //     // CustomUtils::xzxDebug($password);
    //     // CustomUtils::xzxDebug($verifiedPassword);
    //     // CustomUtils::xzxDebug($user["salt"]);
    //     // CustomUtils::xzxDebug($user["password"]);
    //     if ($verifiedPassword !== $user["password"]) {
    //         return false;
    //     }

    //     return true;
    // }

    public function resetAppSecret ($param) {

        $mchInfo = $this->MchInfoDao->get($param['mchId']);

        if (!$mchInfo) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        $update = array();
        $update["appSecret"] = CustomUtils::createAppSecret();

        $this->MchInfoDao->update($param['mchId'], $update);

        $data = $update;

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

}